home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / netz / ipdial / serial.c < prev    next >
C/C++ Source or Header  |  1995-07-21  |  15KB  |  682 lines

  1. /**
  2. ***  IPDial     Script program for initializing a SLIP connection
  3. ***  Copyright  (C)   1994    Jochen Wiedmann
  4. ***
  5. ***  This program is free software; you can redistribute it and/or modify
  6. ***  it under the terms of the GNU General Public License as published by
  7. ***  the Free Software Foundation; either version 2 of the License, or
  8. ***  (at your option) any later version.
  9. ***
  10. ***  This program is distributed in the hope that it will be useful,
  11. ***  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ***  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ***  GNU General Public License for more details.
  14. ***
  15. ***  You should have received a copy of the GNU General Public License
  16. ***  along with this program; if not, write to the Free Software
  17. ***  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ***
  19. ***
  20. ***
  21. ***  This file implements the communication with the serial.device.
  22. ***
  23. ***
  24. ***  Computer: Amiga 1200                       Compiler: Dice 3.01
  25. ***
  26. ***  Author:    Jochen Wiedmann
  27. ***             Am Eisteich 9
  28. ***             72555 Metzingen
  29. ***             Germany
  30. ***
  31. ***             Phone: (+0049) 7123 / 14881
  32. ***             Internet: wiedmann@neckar-alb.de
  33. **/
  34.  
  35.  
  36.  
  37.  
  38.  
  39. /**
  40. ***  Include files
  41. **/
  42. #ifndef IPDIAL_H
  43. #include "IPDial.h"
  44. #endif
  45. #include <ctype.h>
  46. #include <devices/serial.h>
  47. #include <devices/timer.h>
  48.  
  49. #ifndef MIN
  50. #define MIN(a,b) (((a)>(b))?(b):(a))
  51. #endif
  52.  
  53.  
  54.  
  55.  
  56.  
  57. /**
  58. ***  Local variables.
  59. **/
  60. STATIC APTR MySerReq            = NULL;
  61. STATIC APTR MyTimeReq           = NULL;
  62. STATIC UBYTE SerBuffer[4096];
  63.  
  64.  
  65.  
  66.  
  67. /**
  68. ***  Cleanup function.
  69. **/
  70. VOID SerialCleanup(VOID)
  71.  
  72. { DeviceIODelete(MySerReq);
  73.   DeviceIODelete(MyTimeReq);
  74. }
  75.  
  76.  
  77.  
  78.  
  79.  
  80. /**
  81. ***  Table of error messages created by the serial.device.
  82. **/
  83. STATIC VOID SerialShowError(ULONG Error)
  84.  
  85. { STRPTR ptr;
  86.  
  87.   switch(Error)
  88.   { case 1:
  89.       ptr = (STRPTR) "Serial device busy";
  90.       break;
  91.     case 2:
  92.       ptr = (STRPTR) "Baud rate not supported";
  93.       break;
  94.     case 4:
  95.       ptr = (STRPTR) "Memory error";
  96.       break;
  97.     case 5:
  98.       ptr = (STRPTR) "Invalid parameters";
  99.       break;
  100.     case 6:
  101.       ptr = (STRPTR) "Line error";
  102.       break;
  103.     case 9:
  104.       ptr = (STRPTR) "Parity error";
  105.       break;
  106.     case 11:
  107.       ptr = (STRPTR) "Timer error";
  108.       break;
  109.     case 12:
  110.       ptr = (STRPTR) "Buffer overflow";
  111.       break;
  112.     case 13:
  113.       ptr = (STRPTR) "No DSR";
  114.       break;
  115.     case 15:
  116.       ptr = (STRPTR) "Break detected";
  117.       break;
  118.     default:
  119.       ptr = (STRPTR) "Unknown error";
  120.       break;
  121.   }
  122.  
  123.   fprintf(stderr, "Serial device: %s.\n", ptr);
  124. }
  125.  
  126.  
  127.  
  128.  
  129.  
  130. /**
  131. ***  This function opens the serial device. It can be closed
  132. ***  using DeviceIODelete().
  133. **/
  134. STATIC ULONG SerialDecodeProtocol(struct IOExtSer *SerReq, STRPTR Protocol)
  135.  
  136. { if (stricmp((char *) Protocol, "XONXOFF") == 0)
  137.   { SerReq->io_SerFlags &= ~(SERF_XDISABLED|SERF_7WIRE);
  138.   }
  139.   else if (stricmp((char *) Protocol, "NONE") == 0)
  140.   { SerReq->io_SerFlags |= SERF_XDISABLED;
  141.     SerReq->io_SerFlags &= ~SERF_7WIRE;
  142.   }
  143.   else if (stricmp((char *) Protocol, "RTSCTS") == 0  ||
  144.        stricmp((char *) Protocol, "7WIRE") == 0)
  145.   { SerReq->io_SerFlags |= (SERF_XDISABLED|SERF_7WIRE);
  146.   }
  147.   else
  148.   { return(FALSE);
  149.   }
  150.   return(TRUE);
  151. }
  152.  
  153.  
  154.  
  155.  
  156.  
  157. ULONG SerialOpen(STRPTR DeviceName, STRPTR Protocol, ULONG Unit)
  158.  
  159. { ULONG error;
  160.   struct IOExtSer *RealSerReq;
  161.  
  162.   if (!(MySerReq = DeviceIOCreate(sizeof(struct IOExtSer))))
  163.   { fprintf(stderr, "Failed to open %s: Memory error.\n",
  164.         DeviceName);
  165.     exit(10);
  166.   }
  167.   RealSerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  168.   RealSerReq->io_SerFlags = 0;
  169.   if (Protocol)
  170.   { if (!SerialDecodeProtocol(RealSerReq, Protocol))
  171.     { return(FALSE);
  172.     }
  173.   }
  174.   if ((error = DeviceIOOpen(DeviceName, Unit, MySerReq, 0)))
  175.   { SerialShowError(error);
  176.     exit(10);
  177.   }
  178.   if(Protocol)
  179.   { SerialSetProtocol(Protocol);
  180.   }
  181.  
  182.   if (!(MyTimeReq = DeviceIOCreate(sizeof(struct timerequest))))
  183.   { fprintf(stderr, "Failed to open timer.device: Memory error.\n");
  184.     exit(10);
  185.   }
  186.   if ((error = DeviceIOOpen((STRPTR) "timer.device", UNIT_VBLANK,
  187.                      MyTimeReq, 0)))
  188.   { fprintf(stderr, "Failed to open timer.device: Error %ld\n", error);
  189.     exit(10);
  190.   }
  191.   return(TRUE);
  192. }
  193.  
  194.  
  195.  
  196.  
  197.  
  198. /**
  199. ***  This function sends a string to the serial device.
  200. **/
  201. VOID SerialSend(STRPTR str, ULONG len)
  202.  
  203. { struct IOExtSer *req;
  204.  
  205. #ifdef DEBUG
  206.   printf("SerialSend: %s\n", str);
  207. #endif
  208.   req = (struct IOExtSer *) DeviceIOReq(MySerReq);
  209.   req->IOSer.io_Length = strlen((char*) str);
  210.   req->IOSer.io_Data = str;
  211.   DeviceIODo(MySerReq, CMD_WRITE);
  212. }
  213.  
  214.  
  215.  
  216.  
  217.  
  218. /**
  219. ***  This function is used to wait for a certain string.
  220. ***
  221. ***  The function will return if either a timeout occurs
  222. ***  (never happens, if timeout == -1) or if one of the
  223. ***  strings in the args array is read from the serial.device.
  224. ***
  225. ***  Result is the number of the string or -1.
  226. **/
  227. STATIC APTR waitBuffer = NULL;
  228. LONG SerialWait(STRPTR *args, LONG timeout)
  229.  
  230. { ULONG sigs;
  231.   ULONG rsigs;
  232.   BYTE error;
  233.   struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  234.  
  235.   /**
  236.   ***  Be sure, that the buffer is valid.
  237.   **/
  238.   if (!waitBuffer  &&  !(waitBuffer = BufferCreate()))
  239.   { perror("malloc");
  240.     exit(10);
  241.   }
  242.  
  243.   /**
  244.   ***  Clear the buffer.
  245.   **/
  246.   BufferClear(waitBuffer);
  247.  
  248.   sigs = SIGBREAKF_CTRL_C | DeviceIOSignal(MySerReq);
  249.  
  250.   if (timeout != -1)
  251.   { struct timerequest *tr = (struct timerequest *) DeviceIOReq(MyTimeReq);
  252.  
  253.     tr->tr_time.tv_secs = timeout;
  254.     tr->tr_time.tv_micro = 0;
  255.     DeviceIOSend(MyTimeReq, TR_ADDREQUEST);
  256.     sigs |= DeviceIOSignal(MyTimeReq);
  257.   }
  258.  
  259.   for(;;)
  260.   { LONG result;
  261.  
  262.     /**
  263.     ***  First ask, if any data is present on the serial line.
  264.     ***  May be, the string we are waiting for is already present?
  265.     **/
  266.     do
  267.     { DeviceIODo(MySerReq, SDCMD_QUERY);
  268.       if ((result = SerReq->IOSer.io_Actual))
  269.       { SerReq->IOSer.io_Data = SerBuffer;
  270.     SerReq->IOSer.io_Length = MIN(sizeof(SerBuffer)-1, SerReq->IOSer.io_Actual);
  271.     if ((error = DeviceIODo(MySerReq, CMD_READ)))
  272.     { SerialShowError(error);
  273.       exit(10);
  274.     }
  275.     if (EchoMode)
  276.     { int i;
  277.  
  278.       for (i = 0;  i < SerReq->IOSer.io_Actual;  i++)
  279.       { putchar(SerBuffer[i]);
  280.       }
  281.       fflush(stdout);
  282.     }
  283.     BufferExtend(waitBuffer, SerBuffer, SerReq->IOSer.io_Actual);
  284.       }
  285.     }
  286.     while (result);
  287.  
  288.  
  289.     if ((result = BufferCheck(waitBuffer, args)) >= 0)
  290.     { DeviceIOAbort(MyTimeReq);
  291.       return(result);
  292.     }
  293.  
  294.     /**
  295.     ***  It isn't, send a request for one byte.
  296.     **/
  297.     SerReq->IOSer.io_Length = 1;
  298.     SerReq->IOSer.io_Data = SerBuffer;
  299.     DeviceIOSend(MySerReq, CMD_READ);
  300.  
  301.     rsigs = Wait(sigs);
  302.  
  303.     if (rsigs & SIGBREAKF_CTRL_C)
  304.     { printf("Ctrl-C\n");
  305.       exit(10);
  306.     }
  307.     else if (rsigs & DeviceIOSignal(MySerReq))
  308.     { BYTE error;
  309.  
  310.       /**
  311.       ***  Data received, add it to the buffer and check for more.
  312.       **/
  313.       if ((error = DeviceIOWait(MySerReq)))
  314.       { SerialShowError(error);
  315.     exit(10);
  316.       }
  317.       if (EchoMode)
  318.       { putchar(*SerBuffer);
  319.     fflush(stdout);
  320.       }
  321.       BufferExtend(waitBuffer, SerBuffer, 1);
  322.     }
  323.     else
  324.     { /**
  325.       ***  Timeout
  326.       **/
  327.       DeviceIOWait(MyTimeReq);
  328.       DeviceIOAbort(MySerReq);
  329.       return(-1);
  330.     }
  331.   }
  332. }
  333.  
  334.  
  335.  
  336.  
  337. /**
  338. ***  Return buffer read by the last "Wait" command.
  339. **/
  340. STRPTR SerialWaitBuffer(VOID)
  341.  
  342. { if (!(waitBuffer))
  343.   { return((STRPTR) "");
  344.   }
  345.   else
  346.   { return(BufferBuffer(waitBuffer));
  347.   }
  348. }
  349.  
  350.  
  351.  
  352.  
  353.  
  354.  
  355. /**
  356. ***  This function implements a terminal mode. It gives the users input
  357. ***  to the modem and likewise the modems output to the user, as long as
  358. ***  the user doesn't enter Ctrl-\.
  359. **/
  360. VOID SerialTerminal(STRPTR eof, ULONG echo, ULONG lineMode)
  361.  
  362. { struct DosPacket *dp;
  363.   struct MsgPort *port = NULL;
  364.   struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  365.   APTR SerSendReq = NULL;
  366.   struct IOExtSer *serSendReq;
  367.   char buffer[128];
  368.   char sendBuffer[256]; /* Twice the size of buffer */
  369.   ULONG bufSize = sizeof(buffer);
  370.   ULONG status = 10;
  371.   BPTR cis = Input();
  372.   ULONG sigs;
  373.  
  374.   if (!cis)
  375.   { fprintf(stderr, "Can't use nil: as input device.\n");
  376.     exit(10);
  377.   }
  378.  
  379.   if (!echo) {
  380.       lineMode = FALSE;
  381.   }
  382.   if (!lineMode) {
  383.       if (!SetMode(cis, TRUE)) {
  384.       fprintf(stderr, "Can't put console into character (raw) mode.\n");
  385.       exit(10);
  386.       }
  387.       bufSize = 128;
  388.   }
  389.  
  390.  
  391.   if ((dp = AllocDosObject(DOS_STDPKT, NULL)))
  392.   { if ((port = CreateMsgPort()))
  393.     { if ((SerSendReq = DeviceIOCreate(sizeof(struct IOExtSer))))
  394.       { serSendReq = (struct IOExtSer *) DeviceIOReq(SerSendReq);
  395.     serSendReq->IOSer.io_Device = SerReq->IOSer.io_Device;
  396.     serSendReq->IOSer.io_Unit = SerReq->IOSer.io_Unit;
  397.     status = 0;
  398.       }
  399.     }
  400.   }
  401.  
  402.   if (status)
  403.   { fprintf(stderr, "Memory error.\n");
  404.     goto ExitSerialTerminal;
  405.   }
  406.  
  407.   dp->dp_Type = ACTION_READ;
  408.   dp->dp_Arg1 = ((struct FileHandle *) BADDR(cis))->fh_Arg1;
  409.   dp->dp_Arg2 = (ULONG) buffer;
  410.   dp->dp_Arg3 = bufSize;
  411.   SendPkt(dp, (struct MsgPort *) ((struct FileHandle *) BADDR(cis))->fh_Type, port);
  412.  
  413.   SerReq->IOSer.io_Length = 1;
  414.   SerReq->IOSer.io_Data = SerBuffer;
  415.   DeviceIOSend(MySerReq, CMD_READ);
  416.  
  417.   sigs = (1 << port->mp_SigBit) | SIGBREAKF_CTRL_C | DeviceIOSignal(MySerReq);
  418.  
  419.   for(;;)
  420.   { LONG rsigs;
  421.  
  422.     rsigs = Wait(sigs);
  423.  
  424.     if (rsigs & SIGBREAKF_CTRL_C)
  425.     { fprintf(stderr, "Ctrl-C\n");
  426.       status = 5;
  427.       DeviceIOAbort(MySerReq);
  428.       AbortPkt(port, dp);
  429.       WaitPort(port);
  430.       goto ExitSerialTerminal;
  431.     }
  432.  
  433.     if (rsigs & (1 << port->mp_SigBit))
  434.     { int eofSeen = FALSE;
  435.  
  436.       GetMsg(port);
  437.       if (dp->dp_Res1 == -1)
  438.       { fprintf(stderr, "Error %ld while reading input.\n", dp->dp_Res2);
  439.     status = 10;
  440.       }
  441.       if (dp->dp_Res1 == 0)
  442.       { eofSeen = TRUE;
  443.       }
  444.       else
  445.       { int i, bufLen;  /*  Extend LF to CR/LF and send resulting string.   */
  446.  
  447.     bufLen = 0;
  448.     for (i = 0;  i < dp->dp_Res1;  i++)
  449.     { if ((eof  &&  *eof == buffer[i])  ||
  450.           (!eof  &&  !lineMode  &&  buffer[i] == '\0x1c'))
  451.       { eofSeen = TRUE;
  452.       }
  453.       if (lineMode  &&  buffer[i] == '\n')
  454.       { sendBuffer[bufLen++] = '\r';
  455.         sendBuffer[bufLen++] = '\n';
  456.       }
  457.       else
  458.       { sendBuffer[bufLen++] = buffer[i];
  459.       }
  460.     }
  461.  
  462.     if (bufLen > 0)
  463.     { serSendReq->IOSer.io_Length = bufLen;
  464.       serSendReq->IOSer.io_Data = sendBuffer;
  465.       DeviceIODo(SerSendReq, CMD_WRITE);
  466.     }
  467.  
  468.     if (!lineMode  &&  echo)
  469.     { fwrite(sendBuffer, bufLen, 1, stdout);
  470.       fflush(stdout);
  471.     }
  472.       }
  473.  
  474.       if (eofSeen)
  475.       { DeviceIOAbort(MySerReq);
  476.     goto ExitSerialTerminal;
  477.       }
  478.  
  479.       dp->dp_Type = ACTION_READ;
  480.       dp->dp_Arg1 = ((struct FileHandle *) BADDR(cis))->fh_Arg1;
  481.       dp->dp_Arg2 = (ULONG) buffer;
  482.       dp->dp_Arg3 = bufSize;
  483.       SendPkt(dp, (struct MsgPort *) ((struct FileHandle *) BADDR(cis))->fh_Type, port);
  484.     }
  485.  
  486.     if (rsigs & DeviceIOSignal(MySerReq))
  487.     { LONG error;
  488.       LONG result;
  489.  
  490.       if ((error = DeviceIOWait(MySerReq)))
  491.       { SerialShowError(error);
  492.     AbortPkt(port, dp);
  493.     WaitPort(port);
  494.     goto ExitSerialTerminal;
  495.       }
  496.       putchar(*SerBuffer);
  497.       fflush(stdout);
  498.  
  499.       do
  500.       { DeviceIODo(MySerReq, SDCMD_QUERY);
  501.     if ((result = SerReq->IOSer.io_Actual))
  502.     { SerReq->IOSer.io_Data = SerBuffer;
  503.       SerReq->IOSer.io_Length = MIN(sizeof(SerBuffer)-1, SerReq->IOSer.io_Actual);
  504.       if ((error = DeviceIODo(MySerReq, CMD_READ)))
  505.       { SerialShowError(error);
  506.         exit(10);
  507.       }
  508.       fwrite(SerBuffer, SerReq->IOSer.io_Actual, 1, stdout);
  509.       fflush(stdout);
  510.     }
  511.       }
  512.       while (result);
  513.  
  514.       SerReq->IOSer.io_Length = 1;
  515.       SerReq->IOSer.io_Data = SerBuffer;
  516.       DeviceIOSend(MySerReq, CMD_READ);
  517.     }
  518.   }
  519.  
  520.  
  521. ExitSerialTerminal:
  522.   if (dp)
  523.   { FreeDosObject(DOS_STDPKT, dp);
  524.   }
  525.   if (port)
  526.   { DeleteMsgPort(port);
  527.   }
  528.   if (SerSendReq)
  529.   { DeviceIODelete(SerSendReq);
  530.   }
  531.   if (!lineMode)
  532.   { SetMode(cis, FALSE);
  533.   }
  534.   if (status)
  535.   { exit(status);
  536.   }
  537. }
  538.  
  539.  
  540.  
  541.  
  542.  
  543. /**
  544. ***  This function shows the current serial parameters.
  545. **/
  546. VOID SerialShowParms(VOID)
  547.  
  548. { STRPTR Parity, Protocol;
  549.   struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  550.  
  551.   printf("\tBaud = %ld\n", SerReq->io_Baud);
  552.   printf("\tDataBits = %ld\n", (ULONG) SerReq->io_ReadLen);
  553.   printf("\tStopBits = %ld\n", (ULONG) SerReq->io_StopBits);
  554.   printf("\tBufSize = %ld\n", SerReq->io_RBufLen);
  555.   if (SerReq->io_SerFlags & SERF_PARTY_ON)
  556.   { if (SerReq->io_SerFlags & SERF_PARTY_ODD)
  557.     { Parity = (STRPTR) "Odd";
  558.     }
  559.     else
  560.     { Parity = (STRPTR) "Even";
  561.     }
  562.   }
  563.   else
  564.   { Parity = (STRPTR) "None";
  565.   }
  566.   printf("\tParity = %s\n", Parity);
  567.   if (SerReq->io_SerFlags & SERF_7WIRE)
  568.   { if (SerReq->io_SerFlags & SERF_XDISABLED)
  569.     { Protocol = (STRPTR) "RTS/CTS";
  570.     }
  571.     else
  572.     { Protocol = (STRPTR) "RTS/CTS, XON/XOFF";
  573.     }
  574.   }
  575.   else
  576.   { if (SerReq->io_SerFlags & SERF_XDISABLED)
  577.     { Protocol = (STRPTR) "None";
  578.     }
  579.     else
  580.     { Protocol = (STRPTR) "XON/XOFF";
  581.     }
  582.   }
  583.   printf("\tProtocol = %s\n\n", Protocol);
  584. }
  585.  
  586.  
  587.  
  588.  
  589.  
  590. /**
  591. ***  Some functions for setting serial parameters.
  592. **/
  593. VOID SerialSetBaud(ULONG Baud)
  594.  
  595. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  596.   BYTE error;
  597.  
  598.   SerReq->io_Baud = Baud;
  599.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  600.   { SerialShowError(error);
  601.     exit(10);
  602.   }
  603. }
  604. VOID SerialSetDataBits(UBYTE DataBits)
  605.  
  606. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  607.   BYTE error;
  608.  
  609.   SerReq->io_ReadLen = SerReq->io_WriteLen = DataBits;
  610.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  611.   { SerialShowError(error);
  612.     exit(10);
  613.   }
  614. }
  615. VOID SerialSetStopBits(UBYTE StopBits)
  616.  
  617. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  618.   BYTE error;
  619.  
  620.   SerReq->io_StopBits = StopBits;
  621.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  622.   { SerialShowError(error);
  623.     exit(10);
  624.   }
  625. }
  626. VOID SerialSetBufSize(ULONG BufSize)
  627.  
  628. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  629.   BYTE error;
  630.  
  631.   if (BufSize & 0x3f)
  632.   { fprintf(stderr,
  633.         "Warning: BufSize must be a multiple of 64, rounding up.\n");
  634.     BufSize = (BufSize & 0x3f) + 0x40;
  635.   }
  636.   SerReq->io_RBufLen = BufSize;
  637.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  638.   { SerialShowError(error);
  639.     exit(10);
  640.   }
  641. }
  642. ULONG SerialSetParity(STRPTR Parity)
  643.  
  644. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  645.   BYTE error;
  646.  
  647.   if (stricmp((char *) Parity, "NONE") == 0)
  648.   { SerReq->io_SerFlags &= ~SERF_PARTY_ON;
  649.   }
  650.   else if (stricmp((char *) Parity, "EVEN") == 0)
  651.   { SerReq->io_SerFlags |= SERF_PARTY_ON;
  652.     SerReq->io_SerFlags &= ~SERF_PARTY_ODD;
  653.   }
  654.   else if (stricmp((char *) Parity, "ODD") == 0)
  655.   { SerReq->io_SerFlags |= (SERF_PARTY_ON|SERF_PARTY_ODD);
  656.   }
  657.   else
  658.   { return(FALSE);
  659.   }
  660.  
  661.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  662.   { SerialShowError(error);
  663.     exit(10);
  664.   }
  665.   return(TRUE);
  666. }
  667. ULONG SerialSetProtocol(STRPTR Protocol)
  668.  
  669. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  670.   BYTE error;
  671.  
  672.   if (!(SerialDecodeProtocol(SerReq, Protocol)))
  673.   { return(FALSE);
  674.   }
  675.  
  676.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  677.   { SerialShowError(error);
  678.     exit(10);
  679.   }
  680.   return(TRUE);
  681. }
  682.